package com.magist.manage.copyrights.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jeesuite.common.util.DateUtils;
import com.magist.core.entity.CxtHolder;
import com.magist.core.entity.Page;
import com.magist.core.entity.ResultMessage;
import com.magist.core.exception.BusinessException;
import com.magist.core.service.SimpleServiceImpl;
import com.magist.core.util.BeanCompareUtil;
import com.magist.core.util.BeanCopyUtil;
import com.magist.core.util.EnumOrderUtil;
import com.magist.core.util.MAssertUtil;
import com.magist.core.util.ObjectCheckUtil;
import com.magist.manage.constant.BusinessCodeConstant;
import com.magist.manage.copyrights.dao.ContractRightsMapper;
import com.magist.manage.copyrights.dto.ContractRightsDto;
import com.magist.manage.copyrights.entity.ContractRights;
import com.magist.manage.copyrights.entity.Copyrights;
import com.magist.manage.copyrights.entity.SupplyContract;
import com.magist.manage.copyrights.service.ContractRightsService;
import com.magist.manage.copyrights.service.CopyrightsService;
import com.magist.manage.copyrights.service.SupplyContractService;
import com.magist.manage.enums.BackgroundEnum;
import com.magist.manage.enums.BalanceTypeEnum;
import com.magist.manage.enums.CopyrightClassEnum;
import com.magist.manage.enums.CopyrightsRangeEnum;
import com.magist.manage.enums.OpActionEnum;
import com.magist.manage.enums.OpTypeEnum;
import com.magist.manage.enums.TFEnum;
import com.magist.manage.enums.UsedPlatformEnum;
import com.magist.manage.enums.ValidStatusEnum;
import com.magist.manage.util.BusinessCodeGenter;
import com.magist.manage.util.BusinessLogUtil;
import com.magist.manage.web.service.BusinessLogService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

@Service
public class ContractRightsServiceImpl extends SimpleServiceImpl<ContractRights> implements ContractRightsService{

	@Autowired
	private ContractRightsMapper contractRightsMapper;
	@Autowired
	private SupplyContractService supplyContractService;
	@Autowired
	private CopyrightsService copyrightsService;
	@Autowired
    private BusinessCodeGenter businessCodeGenter;
	@Autowired
	private BusinessLogService businessLogService;

	@Autowired
	private BusinessLogUtil businessLogUtil;

	@Override
	public PageInfo<ContractRights> page(Example example, Page page) {
		String orderBy = page.getSort() + " " + page.getOrder();
		if(StringUtils.isEmpty(orderBy.trim())) {
			PageHelper.startPage(page.getCurrPage(), page.getLimit());
		} else {
			PageHelper.startPage(page.getCurrPage(), page.getLimit(),orderBy);
		}
		List<ContractRights> list = this.find(example);
        PageInfo<ContractRights> pageInfo = new PageInfo(list);
		return pageInfo;
	}

    @Override
    public PageInfo<ContractRightsDto> pageDto(ContractRightsDto contractRightsDto, Page page) {
        String orderBy = page.getSort() + " " + page.getOrder();
        if(StringUtils.isEmpty(orderBy.trim())) {
            PageHelper.startPage(page.getCurrPage(), page.getLimit());
        } else {
            PageHelper.startPage(page.getCurrPage(), page.getLimit(),"a." + orderBy);
        }
        List<ContractRightsDto> list = contractRightsMapper.findDto(contractRightsDto);
        PageInfo<ContractRightsDto> pageInfo = new PageInfo(list);
        return pageInfo;
    }

    @Override
	public void addContractRights(ContractRightsDto contractRightsDto) {
		contractRightsDto.setStatis(ValidStatusEnum.VALID.getCode());
		// 校验参数
		this.check(contractRightsDto);
		this.doInsertContract(contractRightsDto);

	}

	@Override
	public int updateContractRights(ContractRightsDto contractRightsDto) {
		// 校验参数
		this.check(contractRightsDto);

		String id = contractRightsDto.getId();
		MAssertUtil.notNull(id,"合同授权信息更新操作主键不能为空");

		ContractRights oldContractRights = this.getById(id);
		String statis = oldContractRights.getStatis();
		if (ValidStatusEnum.INVALID.getCode().equals(statis))
			throw new BusinessException("失效授权不允许修改");
		ContractRights contractRights = new ContractRights();
		BeanUtils.copyProperties(contractRightsDto,contractRights);
		contractRights.setModifyTime(oldContractRights.getModifyTime());
		int update = this.update(contractRights);

		try {
			String compare = BeanCompareUtil.compare(BeanCopyUtil.copy(oldContractRights, ContractRightsDto.class), contractRightsDto);
			businessLogUtil.recordBusinessLog(OpActionEnum.EDIT.getCode(),ContractRights.class.getSimpleName(),contractRights.getId(),"修改授权:" + contractRights.getContractRightsNo(),compare);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return update;
	}

	private void check(ContractRightsDto contractRightsDto) {
		MAssertUtil.notNull(contractRightsDto.getSupplyId(),"请填写供应商主键");
		this.commonCheck(contractRightsDto);
	}

	/**
	 * 一些公共的校验参数
	 * @param contractRightsDto
	 */
	private void commonCheck(ContractRightsDto contractRightsDto) {
		MAssertUtil.notNull(contractRightsDto.getCopyrightsNo(),"请填写唯一版权编号");
		MAssertUtil.notNull(contractRightsDto.getContractNo(),"请填写合同编号");
		MAssertUtil.notNull(contractRightsDto.getCopyrightClass(),"请填写版权权利");
		MAssertUtil.notNull(contractRightsDto.getSoleFlag(),"请填写是否独家授权");
		MAssertUtil.notNull(contractRightsDto.getSubRightsFlag(),"请填写有无转授权");
		MAssertUtil.notNull(contractRightsDto.getProtocolFlag(),"请填写有无补协议");
		MAssertUtil.notNull(contractRightsDto.getBeginDate(),"请填写开始时间");
		MAssertUtil.notNull(contractRightsDto.getEndDate(),"请填写终止时间");
		MAssertUtil.notNull(contractRightsDto.getCopyrightsRange(),"请填写权限使用范围");
		MAssertUtil.notNull(contractRightsDto.getUsedPlatform(),"请填写使用平台");
		MAssertUtil.notNull(contractRightsDto.getOriginalCopyrightsFlag(),"请填写原始版权");
		MAssertUtil.notNull(contractRightsDto.getBalanceType(),"请填写结算形式");
		if(!BalanceTypeEnum.DIVIDE.getCode().equals(contractRightsDto.getBalanceType())) {
			MAssertUtil.notNull(contractRightsDto.getBalance(),"请填写金额");
			MAssertUtil.shorterThan(contractRightsDto.getBalance().toString() , 11, "金额输入过长");
		}

		MAssertUtil.nullOrShorterThan(contractRightsDto.getRemark(),501,"备注过长");
		MAssertUtil.nullOrShorterThan(contractRightsDto.getBalanceRemark(),501,"结算说明过长");
		MAssertUtil.nullOrShorterThan(contractRightsDto.getProtocolNo().toString() , 61, "补充协议合同编号输入过长");

		// 判断时间
		if (contractRightsDto.getBeginDate().after(contractRightsDto.getEndDate())) {
			throw new BusinessException("开始时间不能晚于结束时间");
		}

		// 判断版权是否存在并生效
		Copyrights copyrights = copyrightsService.findByCopyrightsNo(contractRightsDto.getCopyrightsNo());
		MAssertUtil.notNull(copyrights,"版权不存在");
		String worksStatus = copyrights.getWorksStatus();
		if (!ValidStatusEnum.VALID.getCode().equals(worksStatus)) {
			throw new BusinessException("版权已失效");
		}
		if(StringUtils.isEmpty(contractRightsDto.getCopyrightId())) {
			contractRightsDto.setCopyrightId(copyrights.getId());
		}

		// 判断合同是否存在并生效
		SupplyContract supplyContract = supplyContractService.findByContractNo(contractRightsDto.getContractNo());
		MAssertUtil.notNull(supplyContract,"合同不存在");
		String contractStatus = supplyContract.getContractStatus();
		if (!ValidStatusEnum.VALID.getCode().equals(contractStatus)) {
			throw new BusinessException("合同已失效");
		}
		// 根据合同判断
		String balanceType = contractRightsDto.getBalanceType();
		if (!BalanceTypeEnum.BUY.getCode().equals(balanceType)) {
			MAssertUtil.notNull(contractRightsDto.getPartyOneNum(),"请填写甲方比例");
			MAssertUtil.notNull(contractRightsDto.getPartyTwoNum(),"请填写乙方比例");
			Integer contractNum = supplyContract.getContractNum();
			if (contractNum.equals(3)) {
				MAssertUtil.notNull(contractRightsDto.getPartyThreeNum(),"请填写丙方比例");
			}
			// 非买断,判断比例总和是否等于100
			Integer partyOneNum = contractRightsDto.getPartyOneNum()==null?0:contractRightsDto.getPartyOneNum();
			Integer partyTwoNum = contractRightsDto.getPartyTwoNum()==null?0:contractRightsDto.getPartyTwoNum();
			Integer partyThreeNum = contractRightsDto.getPartyThreeNum()==null?0:contractRightsDto.getPartyThreeNum();
			Integer balanceTotal = partyOneNum + partyTwoNum + partyThreeNum;
			if (!balanceTotal.equals(100)) {
				throw new BusinessException("比例总和不为100");
			}
		}

		if (CxtHolder.getUser() != null) {
			contractRightsDto.setModifier(CxtHolder.getUser().getUserName());
		}
		this.checkDataDup(contractRightsDto.getId(),contractRightsDto.getCopyrightsNo(),contractRightsDto.getContractNo());
		contractRightsDto.setSupplyId(supplyContract.getSupplyId());

		String copyrightsNo = contractRightsDto.getCopyrightsNo();

		// 判断有效期(判断该合同剩余有效期是否在6个月以内，如果在6个月以内，该版权即将过期，无法进行版权输出)
		// 1.新增,判断;2.修改无变化,不判断;3.修改改合同,判断.
		String id = contractRightsDto.getId();
		boolean flag = true;
		if (!StringUtils.isEmpty(id)) {
			ContractRights oldRights = this.getById(id);
			String oldCopyrightsNo = oldRights.getCopyrightsNo();
			if (copyrightsNo.equals(oldCopyrightsNo)) {
				flag = false;
			}
		}

		// 判断引入合同是否过期
		if (flag) {
			ResultMessage copyrightsResult = copyrightsService.checkCopyrightsDate(contractRightsDto.getCopyrightsNo());
			if (!copyrightsResult.isSuccess()) {
				throw new BusinessException(copyrightsResult.getMessage());
			}
		}


		// 纠正多选排序
		contractRightsDto.setBackground(EnumOrderUtil.orderEnum(BackgroundEnum.values(), contractRightsDto.getBackground()));
		contractRightsDto.setCopyrightClass(EnumOrderUtil.orderEnum(CopyrightClassEnum.values(), contractRightsDto.getCopyrightClass()));
		contractRightsDto.setCopyrightsRange(EnumOrderUtil.orderEnum(CopyrightsRangeEnum.values(), contractRightsDto.getCopyrightsRange()));
		contractRightsDto.setUsedPlatform(EnumOrderUtil.orderEnum(UsedPlatformEnum.values(), contractRightsDto.getUsedPlatform()));
	}




	@Override
	public void doInvalidByContractId(String contractId) {
		SupplyContract supplyContract = supplyContractService.getById(contractId);
		if(ObjectUtils.isEmpty(supplyContract)) {
			return;
		}
		String contractNo = supplyContract.getContractNo();
		if(StringUtils.isEmpty(contractNo)) {
			return;
		}
		List<ContractRights> contractRights = this.findByContractNo(contractNo);
		if (CollectionUtils.isEmpty(contractRights)) {
			return;
		}
		contractRights.forEach(contractRights1 -> {
			if (ValidStatusEnum.VALID.getCode().equals(contractRights1.getStatis())) {
				contractRights1.setStatis(ValidStatusEnum.INVALID.getCode());
				try {
					// 添加操作日志
					businessLogUtil.recordBusinessLog(OpActionEnum.INVALID.getCode(),OpTypeEnum.ContractRights.getCode(), contractRights1.getId(), "关联失效授权:" + contractRights1.getCopyrightsNo(), "失效合同:" + supplyContract.getContractNo() + ",关联失效授权:" + contractRights1.getContractRightsNo()+";状态:[已生效]改成[已失效];");
				} catch (Exception e) {
					e.printStackTrace();
				}
				update(contractRights1);
			}
		});
	}

	@Override
	public List<ContractRights> findByContractNo(String contractNo) {
		Example example = new Example(ContractRights.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("deleted", "F");
		criteria.andEqualTo("contractNo", contractNo);
		return this.find(example);
	}

	@Override
	public int doInvalidContractRights(String id) {
		int result = 0;
		ContractRights contractRights = this.getById(id);
		ContractRightsDto before = BeanCopyUtil.copy(contractRights, ContractRightsDto.class);
		if(ObjectUtils.isEmpty(contractRights)) {
			return result;
		}
		if (ValidStatusEnum.VALID.getCode().equals(contractRights.getStatis())) {
			contractRights.setStatis(ValidStatusEnum.INVALID.getCode());
			result = this.update(contractRights);
		}
		ContractRightsDto after = BeanCopyUtil.copy(contractRights, ContractRightsDto.class);
		try {
			String compare = BeanCompareUtil.compare(before, after);
			businessLogUtil.recordBusinessLog(OpActionEnum.INVALID.getCode(),OpTypeEnum.ContractRights.getCode(), after.getId(), "失效版权:" + contractRights.getContractRightsNo(), compare);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	@Override
	public void doBatchAdd(List<ContractRightsDto> contractRightsDtos) {
		//约定版权号、合同编号联合为防重复字段
		List<String> checkDup = new LinkedList<>();
		for (int i = 0; i < contractRightsDtos.size(); i++) {
			ContractRightsDto contractRightsDto = contractRightsDtos.get(i);
			if(ObjectCheckUtil.isAllFieldNull(contractRightsDto)) {
				contractRightsDtos.remove(contractRightsDto);
				i--;
				continue;
			}
			try {
				this.checkImport(contractRightsDto);
				// 合同编号和版权号联合为防重复
				String copyrightsNo = contractRightsDto.getCopyrightsNo();
				String contractNo = contractRightsDto.getContractNo();
				String mix = copyrightsNo + contractNo;
				if(checkDup.contains(mix)) {
					throw new BusinessException("导入数据重复,已存在该合同编号和版权号组合的授权");
				} else {
					checkDup.add(mix);
				}
			} catch (Exception e) {
				throw new BusinessException("第" + (i + 1) + "条数据错误," + e.getMessage());
			}
		}
		businessLogUtil.recordBusinessLog(OpActionEnum.IMPORT.getCode(),ContractRights.class.getSimpleName(),null,"导入授权开始","批量导入授权开始,需导入" + contractRightsDtos.size()+"条记录");
		contractRightsDtos.forEach(contractRightsDto->this.doInsertContract(contractRightsDto));
		businessLogUtil.recordBusinessLog(OpActionEnum.IMPORT.getCode(),ContractRights.class.getSimpleName(),null,"导入授权结束","批量导入授权结束,共导入" + contractRightsDtos.size()+"条记录");
	}

	/**
	 * 导入的检查参数
	 * @param contractRightsDto
	 */
	private void checkImport(ContractRightsDto contractRightsDto) {
		this.commonCheck(contractRightsDto);
		// 检查枚举是否正确映射
		MAssertUtil.notNull(TFEnum.getByCode(contractRightsDto.getSoleFlag()),"是否独家授权填写错误");
		MAssertUtil.notNull(TFEnum.getByCode(contractRightsDto.getSubRightsFlag()),"有无转授权填写错误");
		MAssertUtil.notNull(TFEnum.getByCode(contractRightsDto.getProtocolFlag()),"有无补充协议填写错误");
		MAssertUtil.notNull(TFEnum.getByCode(contractRightsDto.getOriginalCopyrightsFlag()),"有无原始版权填写错误");
//待确认		MAssertUtil.notNull(CopyrightClassEnum.getByCode(contractRightsDto.getCopyrightClass()),"版权权利填写错误");
		MAssertUtil.notNull(BalanceTypeEnum.getByCode(contractRightsDto.getBalanceType()),"结算形式填写错误");
		MAssertUtil.notNull(CopyrightClassEnum.getByCode(contractRightsDto.getCopyrightClass().split(",")[0]),"所授权利填写错误");

		MAssertUtil.notNull(CopyrightsRangeEnum.getByCode(contractRightsDto.getCopyrightsRange().split(",")[0]),"权限使用范围填写错误");
		MAssertUtil.notNull(UsedPlatformEnum.getByCode(contractRightsDto.getUsedPlatform().split(",")[0]),"使用平台填写错误");
		String contractNo = contractRightsDto.getContractNo();

		SupplyContract supplyContract = supplyContractService.findByContractNo(contractNo);
		MAssertUtil.notNull(supplyContract,"查询不到合同信息");

	}

	private void doInsertContract(ContractRightsDto contractRightsDto) {
		ContractRights contractRights = new ContractRights();
		BeanUtils.copyProperties(contractRightsDto,contractRights);
		String statis = contractRights.getStatis();
		if(StringUtils.isEmpty(statis)) {
			contractRights.setStatis(ValidStatusEnum.VALID.getCode());
		}
		contractRights.setId(this.getNewId());
		contractRightsDto.setId(contractRights.getId());

		// 生成授权号
		String contractRightsNo = businessCodeGenter.genBusinessCode(BusinessCodeConstant.CONTRACT_RIGHTS_CODE);
		while(!this.checkDuplicationNo(contractRightsNo)) {
			contractRightsNo = businessCodeGenter.genBusinessCode(BusinessCodeConstant.CONTRACT_RIGHTS_CODE);
		}
		contractRights.setContractRightsNo(contractRightsNo);
		if (CxtHolder.getUser() != null) {
			contractRights.setModifier(CxtHolder.getUser().getUserName());
		}
		this.insert(contractRights);

		try {
			String info = BeanCompareUtil.info(BeanCopyUtil.copy(contractRights, ContractRightsDto.class));
			businessLogUtil.recordBusinessLog(OpActionEnum.ADD.getCode(),ContractRights.class.getSimpleName(),contractRights.getId(),"新增授权:" + contractRights.getContractRightsNo(),info);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 判断重复
	 * @param contractRightsNo
	 * @return
	 */
	private boolean checkDuplicationNo(String contractRightsNo) {
		ContractRights contractRights = new ContractRights();
		contractRights.setContractRightsNo(contractRightsNo);
		List<ContractRights> rights = this.find(contractRights);
		if (CollectionUtils.isEmpty(rights)) {
			return true;
		} else {
			return false;
		}
	}

	private void checkDataDup(String id, String copyrightsNo, String contractNo) {
		if(!StringUtils.isEmpty(id)) {
			ContractRights oldContractRights = this.getById(id);
			String oldCopyrightsNo = oldContractRights.getCopyrightsNo();
			String oldContractNo = oldContractRights.getContractNo();
			if (oldCopyrightsNo.equals(copyrightsNo) && oldContractNo.equals(contractNo)) {
				return;
			}
		}
		ContractRights contractRights = this.findByCopyrightsNoAndContractNo(copyrightsNo,contractNo);
		if (!ObjectUtils.isEmpty(contractRights)) {
			throw new BusinessException("授权号合同号相同的授权信息已存在");
		}
	}

	public ContractRights findByCopyrightsNoAndContractNo(String copyrightsNo, String contractNo) {
		ContractRights contractRights = new ContractRights();
		contractRights.setCopyrightsNo(copyrightsNo);
		contractRights.setContractNo(contractNo);
		List<ContractRights> contractRightses = this.find(contractRights);
		if (!CollectionUtils.isEmpty(contractRightses)) {
			return contractRightses.get(0);
		}
		return null;
	}

	@Override
	public void doInvalidByCopyrightsId(String copyrightsId) {
		List<ContractRights> contractRights = this.findByCopyrightsId(copyrightsId);
		contractRights.forEach(contractRights1 -> {
			if (ValidStatusEnum.VALID.getCode().equals(contractRights1.getStatis())) {
				this.doInvalidContractRights(contractRights1.getId());
			}
		});
	}

	@Override
	public List<ContractRights> findByCopyrightsId(String copyrightsId) {
		ContractRights contractRights = new ContractRights();
		contractRights.setCopyrightId(copyrightsId);
		return this.find(contractRights);
	}

	@Override
	public int insert(ContractRights entity) {
		if (CxtHolder.getUser() != null) {
			entity.setModifier(CxtHolder.getUser().getUserName());
		}
		return super.insert(entity);
	}

	@Override
	public int update(ContractRights entity) {
		if (CxtHolder.getUser() != null) {
			entity.setModifier(CxtHolder.getUser().getUserName());
		}
		return super.update(entity);
	}

	@Override
	public List<ContractRights> findByContractNoAndStatus(String contractNo, String status) {
		ContractRights contractRights = new ContractRights();
		contractRights.setContractNo(contractNo);
		contractRights.setStatis(status);
		return this.find(contractRights);
	}

	@Override
	public List<ContractRights> findNearlyExpire(int month) {
		Date dayBegin = DateUtils.getDayBegin(new Date());
		Date endDate = DateUtils.addMonths(dayBegin, month);
		ContractRights contractRights = new ContractRights();
		contractRights.setEndDate(endDate);
		contractRights.setStatis(ValidStatusEnum.VALID.getCode());
		return  this.find(contractRights);
	}

	@Override
	public List<ContractRights> findByCreateById(String userId) {
		if(StringUtils.isEmpty(userId)) {
			return null;
		}
		ContractRights contractRights = new ContractRights();
		contractRights.setCreateById(userId);
		return this.find(contractRights);
	}
}